/* Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.activiti.engine.impl.bpmn.parser.handler;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.activiti.bpmn.constants.BpmnXMLConstants;
import org.activiti.bpmn.model.ActivitiListener;
import org.activiti.bpmn.model.BaseElement;
import org.activiti.bpmn.model.ExtensionElement;
import org.activiti.bpmn.model.ImplementationType;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.delegate.Expression;
import org.activiti.engine.delegate.TaskListener;
import org.activiti.engine.impl.bpmn.parser.BpmnParse;
import org.activiti.engine.impl.calendar.DueDateBusinessCalendar;
import org.activiti.engine.impl.el.ExpressionManager;
import org.activiti.engine.impl.form.DefaultTaskFormHandler;
import org.activiti.engine.impl.form.TaskFormHandler;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.task.TaskDefinition;
import org.apache.commons.lang3.StringUtils;


/**
 * @author Joram Barrez
 */
//增加节点是否可以跳过的属性
public class UserTaskParseHandler extends AbstractActivityBpmnParseHandler<UserTask> {

    public static final String PROPERTY_TASK_DEFINITION = "taskDefinition";

    public Class<? extends BaseElement> getHandledType() {
        return UserTask.class;
    }

    protected void executeParse(BpmnParse bpmnParse, UserTask userTask) {
        ActivityImpl activity = createActivityOnCurrentScope(bpmnParse, userTask, BpmnXMLConstants.ELEMENT_TASK_USER);

        activity.setAsync(userTask.isAsynchronous());
        activity.setExclusive(!userTask.isNotExclusive());

        TaskDefinition taskDefinition = parseTaskDefinition(bpmnParse, userTask, userTask.getId(), (ProcessDefinitionEntity) bpmnParse.getCurrentScope().getProcessDefinition());
        activity.setProperty(PROPERTY_TASK_DEFINITION, taskDefinition);

        //改过的，是否可以AA跳-刘翔宇
        List<ExtensionElement> skiptask = userTask.getExtensionElements().get("skiptask");
        if (skiptask != null) {
            for (ExtensionElement extensionElement : skiptask) {
                activity.setProperty("skiptask", extensionElement.getElementText());
            }
        }

        //节点审批人为空是否可以跳过
        List<ExtensionElement> approvalnullskiptask = userTask.getExtensionElements().get("approvalnullskiptask");
        if (approvalnullskiptask != null) {
            for (ExtensionElement extensionElement : approvalnullskiptask) {
                activity.setProperty("approvalnullskiptask", extensionElement.getElementText());
            }
        }
        //节点跳过时审批意见
        List<ExtensionElement> skiptaskopinion = userTask.getExtensionElements().get("skiptaskopinion");
        if (skiptaskopinion != null) {
            for (ExtensionElement extensionElement : skiptaskopinion) {
                activity.setProperty("skiptaskopinion", extensionElement.getElementText());
            }
        }

        //增加属性,是否可以修改表单
        List<ExtensionElement> actModifyFrom = userTask.getExtensionElements().get("actmodifyfrom");
        if (actModifyFrom != null) {
            for (ExtensionElement extensionElement : actModifyFrom) {
                activity.setProperty("actmodifyfrom", extensionElement.getElementText());
            }
        }

        //增加属性,附件是否必填
        List<ExtensionElement> filerequired = userTask.getExtensionElements().get("filerequired");
        if (filerequired != null) {
            for (ExtensionElement extensionElement : filerequired) {
                activity.setProperty("filerequired", extensionElement.getElementText());
            }
        }

        //是否可以查看审批记录
        List<ExtensionElement> actapprovalrecord = userTask.getExtensionElements().get("actapprovalrecord");
        if (actapprovalrecord != null) {
            for (ExtensionElement extensionElement : actapprovalrecord) {
                activity.setProperty("actapprovalrecord", extensionElement.getElementText());
            }
        }

        //是否可以配置审批记录查看权限
        List<ExtensionElement> actrecordpermissions = userTask.getExtensionElements().get("actrecordpermissions");
        if (actrecordpermissions != null) {
            for (ExtensionElement extensionElement : actrecordpermissions) {
                activity.setProperty("actrecordpermissions", extensionElement.getElementText());
            }
        }

        //默认抄送人
        List<ExtensionElement> ccusers = userTask.getExtensionElements().get("ccusers");
        if (ccusers != null) {
            for (ExtensionElement extensionElement : ccusers) {
                activity.setProperty("ccusers", extensionElement.getElementText());
            }
        }

        //是否可以查看流程图
        List<ExtensionElement> actapprovalpng = userTask.getExtensionElements().get("actapprovalpng");
        if (actapprovalpng != null) {
            for (ExtensionElement extensionElement : actapprovalpng) {
                activity.setProperty("actapprovalpng", extensionElement.getElementText());
            }
        }

        //是否可以ABA跳
        List<ExtensionElement> skiptaskaba = userTask.getExtensionElements().get("skiptaskaba");
        if (skiptaskaba != null) {
            for (ExtensionElement extensionElement : skiptaskaba) {
                activity.setProperty("skiptaskaba", extensionElement.getElementText());
            }
        }

        //是否可以批量办理
        List<ExtensionElement> batch = userTask.getExtensionElements().get("batch");
        if (batch != null) {
            for (ExtensionElement extensionElement : batch) {
                activity.setProperty("batch", extensionElement.getElementText());
            }
        }

        //是否可以加签
        List<ExtensionElement> actaddtask = userTask.getExtensionElements().get("actaddtask");
        if (actaddtask != null) {
            for (ExtensionElement extensionElement : actaddtask) {
                activity.setProperty("actaddtask", extensionElement.getElementText());
            }
        }

        //是否为结束节点
        List<ExtensionElement> endnode = userTask.getExtensionElements().get("endnode");
        if (endnode != null) {
            for (ExtensionElement extensionElement : endnode) {
                activity.setProperty("endnode", extensionElement.getElementText());
            }
        }


        //是否为投票节点
        List<ExtensionElement> isvote = userTask.getExtensionElements().get("isvote");
        if (isvote != null) {
            for (ExtensionElement extensionElement : isvote) {
                activity.setProperty("isvote", extensionElement.getElementText());
            }
        }

        //是否为下一阶段选择审批人
        List<ExtensionElement> selectapproval = userTask.getExtensionElements().get("selectapproval");
        if (selectapproval != null) {
            for (ExtensionElement extensionElement : selectapproval) {
                activity.setProperty("selectapproval", extensionElement.getElementText());
            }
        }

        //节点日文名称
        List<ExtensionElement> jajpname = userTask.getExtensionElements().get("jajpname");
        if (jajpname != null) {
            for (ExtensionElement extensionElement : jajpname) {
                activity.setProperty("jajpname", extensionElement.getElementText());
            }
        }


        //节点英文名称
        List<ExtensionElement> enusname = userTask.getExtensionElements().get("enusname");
        if (enusname != null) {
            for (ExtensionElement extensionElement : enusname) {
                activity.setProperty("enusname", extensionElement.getElementText());
            }
        }


        //节点繁体名称
        List<ExtensionElement> zhtwname = userTask.getExtensionElements().get("zhtwname");
        if (zhtwname != null) {
            for (ExtensionElement extensionElement : zhtwname) {
                activity.setProperty("zhtwname", extensionElement.getElementText());
            }
        }

        // 是否需要申请人选择审批人
        List<ExtensionElement> applychoice = userTask.getExtensionElements().get("applychoice");
        if (applychoice != null) {
            for (ExtensionElement extensionElement : applychoice) {
                activity.setProperty("applychoice", extensionElement.getElementText());
            }
        }

        // 可以查看审批意见的角色
        List<ExtensionElement> viewcommentrole = userTask.getExtensionElements().get("viewcommentrole");
        if (viewcommentrole != null) {
            for (ExtensionElement extensionElement : viewcommentrole) {
                activity.setProperty("viewcommentrole", extensionElement.getElementText());
            }
        }

        // 是否为流程结束节点
        List<ExtensionElement> endtasknode = userTask.getExtensionElements().get("endtasknode");
        if (endtasknode != null) {
            for (ExtensionElement extensionElement : endtasknode) {
                activity.setProperty("endtasknode", extensionElement.getElementText());
            }
        }

        // 是否是电子签章的签约节点
        List<ExtensionElement> electronicseal = userTask.getExtensionElements().get("electronicseal");
        if (electronicseal != null) {
            for (ExtensionElement extensionElement : electronicseal) {
                activity.setProperty("electronicseal", extensionElement.getElementText());
            }
        }


        // 审批时是否可以上传附件
        List<ExtensionElement> uploadfile = userTask.getExtensionElements().get("uploadfile");
        if (uploadfile != null) {
            for (ExtensionElement extensionElement : uploadfile) {
                activity.setProperty("uploadfile", extensionElement.getElementText());
            }
        }

        // 前加签的任务是否可以驳回
        List<ExtensionElement> addbeforetaskrejected = userTask.getExtensionElements().get("addbeforetaskrejected");
        if (addbeforetaskrejected != null) {
            for (ExtensionElement extensionElement : addbeforetaskrejected) {
                activity.setProperty("addbeforetaskrejected", extensionElement.getElementText());
            }
        }

        // 申请人选择审批人的范围(可配置角色标识，多个逗号加个)
        List<ExtensionElement> applychoicescope = userTask.getExtensionElements().get("applychoicescope");
        if (applychoicescope != null) {
            for (ExtensionElement extensionElement : applychoicescope) {
                activity.setProperty("applychoicescope", extensionElement.getElementText());
            }
        }

        // 表单属性获取脚本
        List<ExtensionElement> formsql = userTask.getExtensionElements().get("formsql");
        if (formsql != null) {
            for (ExtensionElement extensionElement : formsql) {
                activity.setProperty("formsql", extensionElement.getElementText());
            }
        }

        activity.setActivityBehavior(bpmnParse.getActivityBehaviorFactory().createUserTaskActivityBehavior(userTask, taskDefinition));
    }

    public TaskDefinition parseTaskDefinition(BpmnParse bpmnParse, UserTask userTask, String taskDefinitionKey, ProcessDefinitionEntity processDefinition) {
        TaskFormHandler taskFormHandler = new DefaultTaskFormHandler();
        taskFormHandler.parseConfiguration(userTask.getFormProperties(), userTask.getFormKey(), bpmnParse.getDeployment(), processDefinition);

        TaskDefinition taskDefinition = new TaskDefinition(taskFormHandler);

        taskDefinition.setKey(taskDefinitionKey);
        processDefinition.getTaskDefinitions().put(taskDefinitionKey, taskDefinition);
        ExpressionManager expressionManager = bpmnParse.getExpressionManager();

        if (StringUtils.isNotEmpty(userTask.getName())) {
            taskDefinition.setNameExpression(expressionManager.createExpression(userTask.getName()));
        }

        if (StringUtils.isNotEmpty(userTask.getDocumentation())) {
            taskDefinition.setDescriptionExpression(expressionManager.createExpression(userTask.getDocumentation()));
        }

        if (StringUtils.isNotEmpty(userTask.getAssignee())) {
            taskDefinition.setAssigneeExpression(expressionManager.createExpression(userTask.getAssignee()));
        }
        if (StringUtils.isNotEmpty(userTask.getOwner())) {
            taskDefinition.setOwnerExpression(expressionManager.createExpression(userTask.getOwner()));
        }
        for (String candidateUser : userTask.getCandidateUsers()) {
            taskDefinition.addCandidateUserIdExpression(expressionManager.createExpression(candidateUser));
        }
        for (String candidateGroup : userTask.getCandidateGroups()) {
            taskDefinition.addCandidateGroupIdExpression(expressionManager.createExpression(candidateGroup));
        }

        // Activiti custom extension

        // Task listeners
        for (ActivitiListener taskListener : userTask.getTaskListeners()) {
            taskDefinition.addTaskListener(taskListener.getEvent(), createTaskListener(bpmnParse, taskListener, userTask.getId()));
        }

        // Due date
        if (StringUtils.isNotEmpty(userTask.getDueDate())) {
            taskDefinition.setDueDateExpression(expressionManager.createExpression(userTask.getDueDate()));
        }

        // Business calendar name
        if (StringUtils.isNotEmpty(userTask.getBusinessCalendarName())) {
            taskDefinition.setBusinessCalendarNameExpression(expressionManager.createExpression(userTask.getBusinessCalendarName()));
        } else {
            taskDefinition.setBusinessCalendarNameExpression(expressionManager.createExpression(DueDateBusinessCalendar.NAME));
        }

        // Category
        if (StringUtils.isNotEmpty(userTask.getCategory())) {
            taskDefinition.setCategoryExpression(expressionManager.createExpression(userTask.getCategory()));
        }

        // Priority
        if (StringUtils.isNotEmpty(userTask.getPriority())) {
            taskDefinition.setPriorityExpression(expressionManager.createExpression(userTask.getPriority()));
        }

        if (StringUtils.isNotEmpty(userTask.getFormKey())) {
            taskDefinition.setFormKeyExpression(expressionManager.createExpression(userTask.getFormKey()));
        }

        // CustomUserIdentityLinks
        for (String customUserIdentityLinkType : userTask.getCustomUserIdentityLinks().keySet()) {
            Set<Expression> userIdentityLinkExpression = new HashSet<Expression>();
            for (String userIdentityLink : userTask.getCustomUserIdentityLinks().get(customUserIdentityLinkType)) {
                userIdentityLinkExpression.add(expressionManager.createExpression(userIdentityLink));
            }
            taskDefinition.addCustomUserIdentityLinkExpression(customUserIdentityLinkType, userIdentityLinkExpression);
        }

        // CustomGroupIdentityLinks
        for (String customGroupIdentityLinkType : userTask.getCustomGroupIdentityLinks().keySet()) {
            Set<Expression> groupIdentityLinkExpression = new HashSet<Expression>();
            for (String groupIdentityLink : userTask.getCustomGroupIdentityLinks().get(customGroupIdentityLinkType)) {
                groupIdentityLinkExpression.add(expressionManager.createExpression(groupIdentityLink));
            }
            taskDefinition.addCustomGroupIdentityLinkExpression(customGroupIdentityLinkType, groupIdentityLinkExpression);
        }

        if (StringUtils.isNotEmpty(userTask.getSkipExpression())) {
            taskDefinition.setSkipExpression(expressionManager.createExpression(userTask.getSkipExpression()));
        }

        return taskDefinition;
    }

    protected TaskListener createTaskListener(BpmnParse bpmnParse, ActivitiListener activitiListener, String taskId) {
        TaskListener taskListener = null;

        if (ImplementationType.IMPLEMENTATION_TYPE_CLASS.equalsIgnoreCase(activitiListener.getImplementationType())) {
            taskListener = bpmnParse.getListenerFactory().createClassDelegateTaskListener(activitiListener);
        } else if (ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION.equalsIgnoreCase(activitiListener.getImplementationType())) {
            taskListener = bpmnParse.getListenerFactory().createExpressionTaskListener(activitiListener);
        } else if (ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION.equalsIgnoreCase(activitiListener.getImplementationType())) {
            taskListener = bpmnParse.getListenerFactory().createDelegateExpressionTaskListener(activitiListener);
        }
        return taskListener;
    }
}
